
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>1、JDBC教案 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>1、JDBC教案 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是JDBC？它的核心思想是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">JDBC (Java Database Connectivity) 是 Java 连接数据库的规范或标准，它允许使用 Java 语言连接数据库并完成 CRUD 操作。其核心思想是，Java 定义了访问数据库的统一接口，而具体的数据库厂商则提供驱动实现类（Driver），从而为多种关系型数据库提供了统一的访问方式。</div>
          </div>
          <div class="card-source">来源: 二、JDBC（Java Database Connectivity）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">使用JDBC进行数据库操作的核心六个步骤是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 注册驱动； 2. 连接数据库； 3. 获取发送SQL的对象； 4. 执行SQL语句； 5. 处理结果； 6. 释放资源。</div>
          </div>
          <div class="card-source">来源: 三、JDBC 开发步骤【重点】</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在处理SQL查询结果时，如何遍历`ResultSet`结果集？获取列数据有哪两种主要方式？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过循环调用`ResultSet`对象的`boolean next()`方法来遍历，该方法会将数据行指针向下移动一行，若当前行有数据则返回`true`。获取列数据主要有两种方式：1. 根据列的编号顺序获取，例如 `rs.getXxx(整数)`，编号从1开始；2. 根据列名获取，例如 `rs.getXxx("列名")`。</div>
          </div>
          <div class="card-source">来源: 4.2 遍历 ResultSet 中的数据</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">安全</div>
          <div class="card-question">什么是SQL注入？文档中提到的避免SQL注入的原理是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">安全</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">SQL注入是指用户输入的数据中包含SQL关键字或语法，并且这些数据参与了SQL语句的编译，导致编译后的SQL语句条件恒为真，从而一直得到非预期的正确结果。避免SQL注入的原理是，让SQL语句在用户输入数据之前就进行预编译，形成完整的SQL结构，之后再将用户数据作为参数填充进去。</div>
          </div>
          <div class="card-source">来源: 七、SQL注入问题</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">相比于`Statement`，`PreparedStatement`接口有哪些主要优点？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`PreparedStatement`的主要优点包括：1. 预编译SQL语句，执行效率更高；2. 安全性高，能有效避免SQL注入问题；3. 可以动态地填充数据，方便执行多个结构相同但参数不同的SQL语句。</div>
          </div>
          <div class="card-source">来源: 8.1 PreparedStatement的应用</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">文档中提到的ORM（对象关系映射）是什么？它解决了什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ORM（Object Relational Mapping）是一种将数据库查询到的零散结果集数据进行封装整理的技术。它通过创建实体类（entity）作为零散数据的载体，将表中的一行数据封装成一个对象，解决了直接处理零散、非结构化数据的不便。</div>
          </div>
          <div class="card-source">来源: 十、ORM</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">什么是DAO（数据访问对象）模式？它在软件设计中的核心作用是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">DAO（Data Access Object）是一种设计模式，它将对同一张数据表的所有操作（如增、删、改、查）都封装在一个特定的对象（例如 XxxDaoImpl）中。其核心作用是实现业务逻辑与数据库访问逻辑的相分离。</div>
          </div>
          <div class="card-source">来源: 十一、 DAO 数据访问对象（Data Access Object）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在JDBC中，如何手动控制事务？请列出相关的三个核心方法。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">通过在`Connection`对象上调用以下三个方法来手动控制事务：1. `conn.setAutoCommit(false)`：关闭自动提交，开启事务；2. `conn.commit()`：手动提交事务；3. `conn.rollback()`：手动回滚事务。</div>
          </div>
          <div class="card-source">来源: 十四、事务</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在多层架构的事务管理中，为什么推荐使用`ThreadLocal`来管理`Connection`对象？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为如果通过方法参数传递`Connection`对象，容易造成接口污染（BadSmell），影响接口设计的通用性。而`ThreadLocal`可以在单个线程中存储一个共享的`Connection`对象，使得在同一个业务流程中的不同层（如Service层和DAO层）能访问到同一个连接，从而保证了事务的一致性，且不污染接口定义。</div>
          </div>
          <div class="card-source">来源: 14.3 解决方案2：ThreadLocal</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">在三层架构中，表示层、业务逻辑层和数据访问层各自的核心职责是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">1. 表示层(View)：负责收集用户的数据和需求，并向用户展示处理结果。2. 业务逻辑层(Service)：负责处理业务逻辑、加工数据、调用DAO层完成具体操作以及控制事务。3. 数据访问层(DAO)：负责向业务层提供数据，并将业务层加工后的数据同步到数据库。</div>
          </div>
          <div class="card-source">来源: 16.1 什么是三层</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">什么是数据库连接池（如Druid）？它主要解决了什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">数据库连接池是在程序初始化时，预先创建指定数量的数据库连接并存储起来。当需要连接时，从池中获取现有连接；使用完毕后，将连接放回池中而不是关闭它。这种机制主要解决了频繁创建和关闭数据库连接导致的资源消耗问题，通过复用连接来节省资源。</div>
          </div>
          <div class="card-source">来源: 十八、Druid连接池</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">API</div>
          <div class="card-question">JDBC API中，`DriverManager`, `Connection`, 和 `Statement` 这三个核心类或接口的主要作用分别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">API</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`java.sql.DriverManager`是一个管理多个数据库驱动类的类，它提供了获取数据库连接的方法。`java.sql.Connection`是一个接口，代表一个数据库连接。`java.sql.Statement`是一个接口，用作发送SQL语句到数据库的工具。</div>
          </div>
          <div class="card-source">来源: 2.2.2 JDBC API</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
